/**
 * 权限声明：
 */
package com.handy.webwork.action.result;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Enumeration;
import java.util.HashMap;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.handy.webwork.action.AbstractAction;
import com.handy.webwork.action.ActionMapping;
import com.handy.webwork.config.HandyConfiguration;
import com.handy.webwork.view.FreemarkerTemplateFactory;
import com.handy.webwork.view.JspSupportServlet;
import com.handy.webwork.view.MessageResource;

import freemarker.ext.jsp.TaglibFactory;
import freemarker.ext.servlet.HttpRequestHashModel;
import freemarker.ext.servlet.ServletContextHashModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * freemarker页面输出
 * 
 * @author rocken.zeng@gmail.com
 * 
 */
public class FreeMarker {
	private static Log log = LogFactory.getLog(FreeMarker.class);

	private HttpServletRequest request;
	private HttpServletResponse response;
	private ServletContext context;

	public FreeMarker(HttpServletRequest request, HttpServletResponse response,
			ServletContext context) {
		this.request = request;
		this.response = response;
		this.context = context;
		if (log.isDebugEnabled()){
			log.info("视图：FreeMarker输出。");
		}
	}

	@SuppressWarnings("unchecked")
	public void doFreeMarker(ActionMapping actionMapping,AbstractAction action,String contentType, String resultFileName) {
		doFreeMarker(actionMapping,action,contentType, resultFileName, new HashMap());
	}

	/**
	 * 当result类型为freemarker时，处理页面。
	 * 
	 * @param action
	 * @param resultFileName
	 * @param root
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public void doFreeMarker(ActionMapping actionMapping,AbstractAction action,String contentType, String resultFileName, HashMap root){
		if (log.isDebugEnabled()) {
			log.info("doFreeMarker()");
			log.info(resultFileName);
		}
		if (root == null) {
			root = new HashMap();
		}
		//将bean值加入到root中，以便传值到freemarker.
		if (HandyConfiguration.autoHandleParam()) {// 自动将action的get,set字段装载到root中，在视图中显示。
			try {
				root.putAll(PropertyUtils.describe(action));
			} catch (IllegalAccessException e) {
				log.error(e.getMessage());
			} catch (InvocationTargetException e) {
				log.error(e.getMessage());
			} catch (NoSuchMethodException e) {
				log.error(e.getMessage());
			}
		} else {
			HashMap _root = action.sendData();
			if (null != _root) {
				root.putAll(_root);
			}
		}
		
		root.remove("request");
		root.remove("Session");
		root.remove("session");
		// request
		root.put("request", request);
		// session
		root.put("Session", getSession());
		root.put("session", request.getSession(true));
		// messageRessource
		root.put("action", MessageResource.getInstance());
		// 将action所属插件名传到视图
		if (null == actionMapping.getPluginName()){
			root.put("plugin", "");
		}else{
			root.put("plugin", actionMapping.getPluginName());
		}
		
		String webRoot = request.getContextPath();
		String actionRoot = "";
		if (null == actionMapping.getPluginRoot() || "".equals(actionMapping.getPluginRoot())){
			actionRoot = webRoot;
		}else{
			actionRoot = webRoot+"/"+actionMapping.getPluginRoot();
		}
		root.put("webRoot", webRoot);//站点根路径
		root.put("actionRoot", actionRoot);//action根路径
		
		// 使freemarker解析jsp taglib
		HttpServlet jspSupport = JspSupportServlet.jspSupportServlet;
		if (jspSupport != null) {
			ServletContextHashModel servletContextModel = new ServletContextHashModel(
					JspSupportServlet.jspSupportServlet, getObjectWrapper());
			TaglibFactory taglibs = new TaglibFactory(context);
			HttpRequestHashModel requestModel = new HttpRequestHashModel(
					request, response, getObjectWrapper());

			root.put(KEY_APPLICATION, servletContextModel);
			root.put(KEY_JSP_TAGLIBS, taglibs);
			root.put(KEY_REQUEST_MODEL, requestModel);
		}

		if (null != root.get(AbstractAction.HANDY_DYNA_FTL) && !"".equals((String)root.get(AbstractAction.HANDY_DYNA_FTL))) {
			resultFileName = (String)root.get(AbstractAction.HANDY_DYNA_FTL);
		} 
		if (null != root.get(AbstractAction.HANDY_DYNA_FTL_CONTENT_TYPE)){
			contentType = (String)root.get(AbstractAction.HANDY_DYNA_FTL_CONTENT_TYPE);
		}
		if (null == contentType || "".equals(contentType)){
			contentType = "text/html";
		}
		
		try {
			Template t = FreemarkerTemplateFactory.getInstance().create(
					resultFileName);
			StringBuffer sb = new StringBuffer();
			sb.append(contentType).append("; charset=").append(t.getEncoding());
			response.setContentType(sb.toString());
			t.process(root, response.getWriter());// 输出
		} catch (TemplateException e) {
			log.error(e.getMessage());
		} catch (IOException e) {
			log.error(e.getMessage());
		}

	}

	/**
	 * 将session中的值转存到map中。
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private HashMap getSession() {
		HashMap map = new HashMap();
		HttpSession session = request.getSession();
		Enumeration names = session.getAttributeNames();
		while (names.hasMoreElements()) {
			String name = (String) names.nextElement();
			map.put(name, session.getAttribute(name));
		}
		return map;
	}

	private ObjectWrapper getObjectWrapper() {
		return ObjectWrapper.DEFAULT_WRAPPER;
	}

	public static final String KEY_APPLICATION = "Application";
	public static final String KEY_REQUEST_MODEL = "Request";
	public static final String KEY_JSP_TAGLIBS = "JspTaglibs";
}
